package judesart.app.server;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import judesart.app.client.controller.ExhibitionController;
import judesart.app.domain.Address;
import judesart.app.domain.Artist;
import judesart.app.domain.Artwork;
import judesart.app.domain.Exhibition;
import judesart.app.domain.ExhibitionArtwork;
import judesart.app.domain.ExhibitionPhoto;
import judesart.app.domain.ExhibitionType;
import judesart.app.domain.ExhibitionVideo;
import judesart.app.domain.User;
import judesart.app.repository.ArtistDAO;
import judesart.app.repository.ArtworkDAO;
import judesart.app.repository.ExhibitionDAO;
import judesart.app.service.UserService;
import judesart.app.service.VideosService;
import judesart.app.shared.ArtworkShort;
import judesart.app.shared.SearchResult;
import judesart.app.shared.UploadToken;
import judesart.app.shared.ValidationException;
import judesart.common.bean.ApplicationContextProvider;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class ExhibitionControllerImpl extends RemoteServiceServlet implements
        ExhibitionController {
    private static final long serialVersionUID = 1L;

    private final static Log LOGGER = LogFactory.getLog(ExhibitionControllerImpl.class);

    ExhibitionDAO exhibitionDAO = ApplicationContextProvider.getCtx().getBean(
            ExhibitionDAO.class);
    ArtistDAO artistDAO = ApplicationContextProvider.getCtx().getBean(
            ArtistDAO.class);
    ArtworkDAO artworkDAO = ApplicationContextProvider.getCtx().getBean(
            ArtworkDAO.class);
    UserService userService = ApplicationContextProvider.getCtx().getBean(
            UserService.class);
    VideosService videoService = ApplicationContextProvider.getCtx().getBean(
            VideosService.class);

    @Override
    public Exhibition getExhibition(Long exhibitionId) {
        Exhibition exhibition = exhibitionDAO.findExhibitionById(exhibitionId);
        setTransientFields(exhibition);
        mainPhotoFirst(exhibition);
        return exhibition;
    }

	private void mainPhotoFirst(Exhibition exhibition) {
		for(ExhibitionPhoto ep : exhibition.getPhotos()) {
        	if (ep.getMainImage()!= null && ep.getMainImage()) {
        		exhibition.getPhotos().remove(ep);
        		exhibition.getPhotos().add(0, ep);
        		break;
        	}
		}
	}

    private void setTransientFields(Exhibition exhibition) {
        if (exhibition.getArtworks() != null
                && exhibition.getArtworks().size() > 0) {
            for (ExhibitionArtwork exhibitionArtwork : exhibition.getArtworks()) {
                Artwork artwork = artworkDAO.findArtworkById(exhibitionArtwork.getArtworkId());
                if (artwork.getPhotos() != null
                        && artwork.getPhotos().size() > 0) {
                    exhibitionArtwork.setMainImageId(artwork.getPhotos().get(0).getImageId());
                }
            }
        }
    }

    @Override
    public SearchResult<Exhibition> searchExhibitions(int startAt,
            int maxElements) {
        Long artistId = getArtistId();
        int count = exhibitionDAO.countExhibitions(artistId);
        List<Exhibition> results = exhibitionDAO.findExhibitions(artistId,
                startAt, maxElements);
        for (Exhibition exhibition : results) {
            mainPhotoFirst(exhibition);
        }
        LOGGER.debug(" > searchExhibitions : " + results.size());
        return new SearchResult<Exhibition>(new ArrayList<Exhibition>(results), count);
    }

    private Long getArtistId() {
        Long artistId;
        User user = userService.getCurrentUser();
        if (user != null) {
            Artist artist = artistDAO.findArtistByUserId(user.getId());
            artistId = artist.getId();
        } else {
            artistId = null;
        }
        return artistId;
    }

    @Override
    public Exhibition createExhibition(Exhibition exhibition)
            throws ValidationException {
        exhibition.setArtistId(getArtistId());
    	if (exhibition.getType() == null){
    		exhibition.setType(ExhibitionType.UNDEFINED);
    	}
        return exhibitionDAO.createExhibition(exhibition);
    }

    @Override
    public void deleteExhibition(Long exhibitionId) {
        exhibitionDAO.deleteExhibition(exhibitionId);
    }

    @Override
    public Exhibition updateExhibition(Exhibition exhibition)
            throws ValidationException {
    	if (exhibition.getType() == null){
    		exhibition.setType(ExhibitionType.UNDEFINED);
    	}
        return exhibitionDAO.updateExhibition(exhibition);
    }

    @Override
    public String findPhotoKeyByImageId(Long imageId) {
        return exhibitionDAO.findExhibitionPhotoKeyByImageId(imageId);
    }

    @Override
    public UploadToken getVideoUploadFormToken(Long exhibitionId) {
        Exhibition exhibition = exhibitionDAO.findExhibitionById(exhibitionId);
        String title = exhibition.getTitle();
        String description;
        if (exhibition.getDetail() != null)
            description = exhibition.getDetail().getValue();
        else
            description = "";
        String location;
        Address address = exhibition.getGalleryAddress();
        if (address != null && address.getCity() != null
                && address.getCity().trim().length() > 0
                && address.getCountry() != null)
            location = address.getCity() + ", " + address.getCountry().title();
        else
            location = "";
        return videoService.getFormUploadToken(title, description, location,
                "exhibition_" + exhibition.getId().toString());
    }

    @Override
    public ExhibitionVideo addYoutubeVideoById(Long exhibitionId, String videoId) {
        Exhibition exhibition = exhibitionDAO.findExhibitionById(exhibitionId);
        exhibition = exhibitionDAO.addVideoToExhibition(exhibition, videoId);
        return exhibition.getVideos().get(exhibition.getVideos().size() - 1);
    }

    @Override
    public List<ArtworkShort> findExhibitionArtworks(Long exhibitionId) {
        if (exhibitionId == null) {
            return new ArrayList<ArtworkShort>();
        }
        Exhibition exhibition = exhibitionDAO.findExhibitionById(exhibitionId);
        List<ExhibitionArtwork> exhArts = exhibition.getArtworks();
        List<ArtworkShort> arts = new ArrayList<ArtworkShort>();
        for (ExhibitionArtwork exhibitionArtwork : exhArts) {
            Artwork artwork = artworkDAO.findArtworkById(exhibitionArtwork.getArtworkId());
            ArtworkShort xort = new ArtworkShort();
            xort.setId(artwork.getId());
            if (artwork.getPhotos() != null && artwork.getPhotos().size() > 0) {
                xort.setImageId(artwork.getPhotos().get(0).getImageId());
            }
            xort.setTitle(artwork.getTitle());
            arts.add(xort);
        }
        return arts;
    }

    @Override
    public void addArtworkToExhibition(Long exhibitionId, Long artworkId) {
        LOGGER.debug(" >> addArtworkToExhibition [" + exhibitionId + "]");
        Exhibition exhibition = exhibitionDAO.findExhibitionById(exhibitionId);
        Artwork artwork = artworkDAO.findArtworkById(artworkId);
        exhibitionDAO.addArtworkToExhibition(exhibition, artwork);
    }

    @Override
    public void deleteArtworkFromExhibition(Long exhibitionId, Long artworkId) {
        Exhibition exhibition = exhibitionDAO.findExhibitionById(exhibitionId);
        Artwork artwork = artworkDAO.findArtworkById(artworkId);
        exhibitionDAO.deleteArtworkFromExhibition(exhibition, artwork);
    }

    @Override
    public List<Exhibition> findAllUserExhibitions(Long userId) {
        Artist artist = artistDAO.findArtistByUserId(userId);
        List<Exhibition> results = new ArrayList<Exhibition>(exhibitionDAO.findExhibitions(
                artist.getId(), 0, 100));
        for (Exhibition exhibition : results) {
            mainPhotoFirst(exhibition);
        }
        return results;
    }

}
